﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using GTA;

namespace ProgressbarOverlay_Demo
{
    public class ProgressbarOverlay_DemoScript : Script
    {
        GTAHookAdv.Overlay.ProgressBarOverlay _progressbarCarEngine;
        GTAHookAdv.Overlay.ProgressBarOverlay _progressbarCarFuelTank;
        GTAHookAdv.Overlay.ProgressBarOverlay _progressCarHealth;
        GTAHookAdv.Overlay.ProgressBarOverlay _progressCarSpeed;

        private enum Status
        {
            Stopped = 0,
            Starting = 1,
            Started = 2
        }

        private Status _status = Status.Stopped;

        public ProgressbarOverlay_DemoScript()
        {
            this.GUID = new Guid("{AE42F2AC-E6B4-45E1-BB43-F5E6BBF20C22}");
            
            
            this.GeneralInfo  = "ProgressbarOverlay Demo\r\n\r\n";
            this.GeneralInfo +="Demonstrate how to use ProgressbarOverlay with GTA4HookAdv.\r\n\r\n";
            this.GeneralInfo +="Get in a car to see 4 progressbars showing current vehicle state.\r\n";
            this.GeneralInfo +="Each progressbar has its own style, and most of them will blink when value goes bellow 25%";

            this.Interval = 40;
            this.BindScriptCommand("Start", new ScriptCommandDelegate(OnStart));
            this.BindScriptCommand("Stop", new ScriptCommandDelegate(OnStop));
        }

        private void OnStop(Script sender, ObjectCollection Parameter)
        {
            GTAHookAdv.g_Game.DisplaySubTitle("Stopping Progressbar Overlay Demo", 7000, Color.Red);
            this.Tick -= On_Tick;
            //It is important to dispose Overlay components when it is not used anymore, as it consume Graphical memory and CPU time.
            if(_progressbarCarEngine != null)
                try { _progressbarCarEngine.Dispose(); }
                catch { }
            if (_progressbarCarFuelTank != null)
                try { _progressbarCarEngine.Dispose(); }
                catch { }
            if (_progressCarHealth != null)
                try { _progressbarCarEngine.Dispose(); }
                catch { }
            if (_progressCarSpeed != null)
                try { _progressbarCarEngine.Dispose(); }
                catch { }
            //Dereferencing progressbars will also call a Dispose on them, but you can't control when it will be disposed.
            _progressbarCarEngine = null;
            _progressbarCarFuelTank = null;
            _progressCarHealth = null;
            _progressCarSpeed = null;
            _status = Status.Stopped;
        }

        private void OnStart(Script sender, ObjectCollection Parameter)
        {
            if (_status != Status.Stopped)
                return;
            BuildProgressBars();
            this.Tick += On_Tick;
            GTAHookAdv.g_Game.DisplaySubTitle("Get in a car to see the progress bars", 20000, Color.Green);
            _status = Status.Started;
        }

        private void BuildProgressBars()
        {
            //Sizes and Positions are based on a 1920x1080 Resolution. If Game Resolution is different no worry : it will be automaticly scalled/moved to fit.

            

            //Position of the first progressbar
            Point pos = new Point(50, 650);
            
            _progressbarCarEngine = new GTAHookAdv.Overlay.ProgressBarOverlay(this); //It is important to give this as it need the PerFrameDrawing event.
            _progressbarCarEngine.Location = pos;
            _progressbarCarEngine.Size = new Size(300, 25);
            _progressbarCarEngine.BorderColor = Color.Blue;
            _progressbarCarEngine.BackColor = Color.Black;
            _progressbarCarEngine.ForeColor = Color.White;
            _progressbarCarEngine.Opacity = 25; // the progressbar will mostly be transparent (25% visible)
            _progressbarCarEngine.Visible = false; //We'll display it only when the player is in a car

            //This position technique is not cool, you'll see with OverlayPanel_Demo that placement can be done easier ;)
            pos.Offset(new Point(0, _progressbarCarEngine.Size.Height + 3)); //We move the position for the next progressbar 3 pixels bellow previous progressbar
            _progressbarCarFuelTank = new GTAHookAdv.Overlay.ProgressBarOverlay(this);
            _progressbarCarFuelTank.Size = new Size(300, 20);
            _progressbarCarFuelTank.Location = pos;
            _progressbarCarFuelTank.BorderColor = Color.Orange;
            _progressbarCarEngine.ForeColor = Color.White;
            _progressbarCarFuelTank.Visible = false;

            pos.Offset(new Point(0, _progressbarCarFuelTank.Size.Height + 3));
            _progressCarHealth = new GTAHookAdv.Overlay.ProgressBarOverlay(this);
            _progressCarHealth.Size = new Size(300, 20);
            _progressCarHealth.Location = pos;
            _progressCarHealth.BorderColor = Color.DarkGreen;
            _progressbarCarEngine.ForeColor = Color.White;
            _progressCarHealth.Opacity = 30;
            _progressCarHealth.Visible = false;

            pos.Offset(new Point(0, _progressCarHealth.Size.Height + 3));
            _progressCarSpeed = new GTAHookAdv.Overlay.ProgressBarOverlay(this);
            _progressCarSpeed.Size = new Size(300, 18);
            _progressCarSpeed.Location = pos;
            _progressCarHealth.BorderColor = Color.Purple;
            _progressbarCarEngine.ForeColor = Color.White;
            _progressCarSpeed.Visible = false;
            _progressCarSpeed.Minimum = 0;
            _progressCarSpeed.Maximum = 150; //We adjust range to display speed from 0 to 150 km/hrs

            //Now look at On_Tick method for further details
        }

        void On_Tick(object sender, EventArgs e)
        {
            if (_status == Status.Started)
            {
                bool isInVehicle = Player.Character.CurrentVehicle != null && Player.Character.CurrentVehicle.Exists();
               
                //Lets display controls only when player is in a car
                _progressbarCarEngine.Visible = isInVehicle;
                _progressbarCarFuelTank.Visible = _progressbarCarEngine.Visible;
                _progressCarHealth.Visible = _progressbarCarEngine.Visible;
                _progressCarSpeed.Visible = _progressbarCarEngine.Visible;

                //Now lets refresh _progressbar behaviours
                if (isInVehicle)
                {
                    if (Player.Character.isGettingIntoAVehicle)
                    {

                        InitProgressBarsMaximumValue();
                    }
                    //We set a new Value to the progressbar.
                    //Keep in mind that values will change on every tick, so if this.Interval is Huge, Value will change slooowly (only once per sec if Interval = 1000)

                    RefreshProgressBarValue(_progressbarCarEngine, Player.Character.CurrentVehicle.EngineHealth);
                    RefreshProgressBarValue(_progressbarCarFuelTank, Player.Character.CurrentVehicle.PetrolTankHealth);
                    RefreshProgressBarValue(_progressCarHealth, Player.Character.CurrentVehicle.Health);
                    RefreshProgressBarValue(_progressCarSpeed, ConvertSpeedToKmPerHour(Player.Character.CurrentVehicle.Speed) );

                    //Lets display some texts into controls

                    //ValuePercent return from 0 to 100 representing a %
                    //e.g : Minimum = 0 Maximum = 200 Value = 100 ==> 50%
                    _progressbarCarEngine.Text = String.Format("{0}%", _progressbarCarEngine.ValuePercent);
                    _progressbarCarFuelTank.Text = String.Format("{0}%", _progressbarCarFuelTank.ValuePercent);
                    _progressCarHealth.Text = String.Format("{0}%", _progressCarHealth.ValuePercent);
                    _progressCarSpeed.Text = String.Format("{0} km/h", _progressCarSpeed.Value); //See ConvertSpeedToKmPerHour

                    //Now let's play with colors
                    if(_progressCarSpeed.Value == _progressCarSpeed.Maximum)
                        _progressCarSpeed.ForeColor =  Color.Red;
                    else
                        _progressCarSpeed.ForeColor =  SystemColors.Highlight;


                    AlertIfPoorValue(_progressbarCarEngine); //See method comment
                    AlertIfPoorValue(_progressbarCarFuelTank);
                    
                } 

            }
        }


        /// <summary>
        /// Consider this as a demo of : ValuePercent Field , Blink Field , and ForeColor Field
        /// </summary>
        /// <param name="progressbar"></param>
        private void AlertIfPoorValue(GTAHookAdv.Overlay.ProgressBarOverlay progressbar)
        {
            //If value is less than 25 %
            if (progressbar.ValuePercent <= 25)
            {
                //Progressbar will blink and its bar color will be red
                progressbar.Blink = true;
                progressbar.ForeColor = Color.Red;
            }
            else
            {
                //Otherwise stop blinking and set bar color to default
                progressbar.Blink = false;
                progressbar.ForeColor = SystemColors.Highlight;
            }
        }

        private float ConvertSpeedToKmPerHour(float p)
        {
            //Not really important to understand here, just , the result will be km/hrs (based on basic trainer behaviour)
            return p * 2.249f * 1.6f;
        }

        /// <summary>
        /// Set the value to the progressbar, it also make sure that value will not exceed Minimum or Maximum
        /// <remarks>Remember that all overlay controls inherrit from System.Windows.Forms.Controls.
        /// Regarding System.Windows.Forms.Progressbar if Value is less than Minimum or greater than Maximum, an exception will be thrown
        /// That's why i made this method in this demo.Up to you then to manage minimum / maximum as you wish</remarks>
        /// </summary>
        /// <param name="control">the targetted progressbar witch we want to set a new Value</param>
        /// <param name="value">the value to Set</param>
        private void RefreshProgressBarValue(GTAHookAdv.Overlay.ProgressBarOverlay control, float value)
        {
            //Progressbar.Value is an Int32 type Field
            int nextval = Convert.ToInt32(value);
            //Check mini maxi
            if (nextval < control.Minimum)
                nextval = control.Minimum;
            else if (nextval > control.Maximum)
                nextval = control.Maximum;
            //Apply the value
            control.Value = nextval;
        }

        /// <summary>
        /// Eatch kind of vehicle have its own maximum health property. So we get it and make progressbars fits to it.
        /// </summary>
        private void InitProgressBarsMaximumValue()
        {
            //Vehcile class doesn't have a GetMaxHealth Field, so we have to do a small hack :
            //We build a clone of the vehicle, this clone will not be damaged as it is a fresh one.
            Vehicle vehi = GTA.World.CreateVehicle(Player.Character.CurrentVehicle.Model, new Vector3(300, 300, 300));
            //Now we know what are the Maximum heath values, let's use them :
            _progressbarCarEngine.Maximum = Convert.ToInt32(vehi.EngineHealth);
            _progressbarCarFuelTank.Maximum = Convert.ToInt32(vehi.PetrolTankHealth);
            _progressCarHealth.Maximum = Convert.ToInt32(vehi.Health);
            vehi.Delete();
            //Note : this hack wes not really ressources consumming as the model and textures were allready into memory ;)
        }
    }
}
